const lowCodeInstance = Symbol("lowCodeInstance");
import clone from "clone";
import { v4 as uuidv4 } from "uuid";
import { tools } from "../page-designer/utils";
import { LowCodeImp, ComponentImp, CellImp, TabImp, ComponentType } from "./type";
export class Component implements ComponentImp {
  private [lowCodeInstance]: LowCodeImp;
  private metaRefresh?: string;
  key!: string;
  component!: ComponentType;
  name!: string;
  field!: string;
  selector!: string;
  group!: string;
  describe!: string;
  nestedChain!: string;
  componentProps!: any;
  style?: any;
  items!: Array<ComponentImp | CellImp | TabImp>;
  [prop: string]: any;
  constructor(
    componentProps: { [x: string]: any; },
    lowcode: LowCodeImp,
    newKey?: boolean
  ) {


    for (let name in componentProps) {
      if (componentProps.hasOwnProperty(name)) {
        this[name] = clone(componentProps[name]);
      }
    }
    this[lowCodeInstance] = <LowCodeImp>lowcode;
    if (!this.key || newKey) {
      this.key = uuidv4();
    }
    if (!this.selector) {
      this.selector = this.component + "_" + tools.random(5);
    }
    this.modelBing();
  }

  updateMetaRefresh() {
    this.metaRefresh = uuidv4();
  }
  getLowCodeInstance() {
    return this[lowCodeInstance];
  }

  addItem(com: ComponentImp): ComponentImp;
  addItem(com: CellImp): CellImp;
  addItem(com: TabImp): TabImp;
  addItem(
    com: ComponentImp | CellImp | TabImp
  ): ComponentImp | CellImp | TabImp {
    let _this = this[lowCodeInstance];

    let componentInstance;
    if ((<ComponentImp>com).group) {
      componentInstance = <Component>new Component(com, _this);
    } else {
      componentInstance = com as CellImp | TabImp;
      componentInstance.key = tools.random();
    }
    _this.dataCenter[componentInstance.key] = componentInstance;
    if (componentInstance.items && componentInstance.items.length > 0) {
      componentInstance.items = componentInstance.items.map((item) => {
        return this.addItem(item);
      });
    }
    return componentInstance;
  }

  copyItem(com: ComponentImp, newkey: boolean): ComponentImp;
  copyItem(com: CellImp, newkey: boolean): CellImp;
  copyItem(com: TabImp, newkey: boolean): TabImp;
  copyItem(
    com: ComponentImp | CellImp | TabImp,
    newkey: boolean
  ): ComponentImp | CellImp | TabImp {
    let _this = this[lowCodeInstance];
    let componentInstance: CellImp<any>;
    if ((<ComponentImp>com).group) {
      componentInstance = <Component>new Component(com, _this, newkey);
    } else {
      componentInstance = com as CellImp | TabImp;
      componentInstance.key = tools.random();
    }
    _this.dataCenter[componentInstance.key] = componentInstance;
    if (componentInstance.items && componentInstance.items.length > 0) {
      componentInstance.items = componentInstance.items.map(
        (item: ComponentImp | CellImp | TabImp) => {
          return this.copyItem(item, newkey);
        }
      );
    }
    return componentInstance;
  }

  removeItem(key: string) {
    let _this = this[lowCodeInstance];
    const componentInstance = _this.dataCenter[key];
    if (componentInstance && componentInstance.items && componentInstance.items.length > 0) {
      componentInstance.items = componentInstance.items.map(
        (item: Component | CellImp | TabImp) => {
          return this.removeItem(item.key);
        }
      );
    }
    delete _this.dataCenter[key];
  }

  modelBing() {
    let map: { [key: string]: any } = this[lowCodeInstance].model;

    let field = this.field;
    this["componentProps"]&&Object.defineProperty(this["componentProps"], "value", {
      get() {
        if (field) {
          return map[field];
        }
      },
      set(value) {
        if (field) {
          map[field] = value;
        }
      },
    });
  }
}
